package com.university.mentalhealthplatform.global.rbac.service.entity;

import com.university.mentalhealthplatform.global.rbac.dto.normal.EndpointDTO;
import com.university.mentalhealthplatform.global.rbac.dto.normal.SimpleEndpointDTO;
import com.university.mentalhealthplatform.exception.EndpointNotFoundException;
import com.university.mentalhealthplatform.global.rbac.model.AccessLevel;
import com.university.mentalhealthplatform.global.rbac.model.Endpoint;
import com.university.mentalhealthplatform.global.rbac.model.Permission;
import com.university.mentalhealthplatform.global.rbac.repository.EndpointRepository;
import com.university.mentalhealthplatform.global.rbac.repository.PermissionRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class EndpointService {

    @Autowired
    private EndpointRepository endpointRepository;

    @Autowired
    private PermissionRepository permissionRepository;

    public List<Endpoint> getAllEndpoints() {
        return endpointRepository.findAll();
    }

    public Optional<Endpoint> getEndpointById(Long id) {
        return endpointRepository.findById(id);
    }

    public Endpoint createEndpointIfNotFound(String path, String method, AccessLevel accessLevel, boolean allowAnonymous) {
        // 尝试查找是否已存在对应的 Endpoint
        Optional<Endpoint> existingEndpoint = endpointRepository.findByPathAndMethod(path, method);

        // 如果 Endpoint 已存在，直接返回
        if (existingEndpoint.isPresent()) {
            return existingEndpoint.get();
        }

        // 如果 Endpoint 不存在，创建并保存新的 Endpoint
        Endpoint endpoint = new Endpoint();
        endpoint.setPath(path);
        endpoint.setMethod(method);
        endpoint.setAccessLevel(accessLevel);
        endpoint.setAllowAnonymous(allowAnonymous);

        return endpointRepository.save(endpoint);
    }


    // 切换接口状态（启用/禁用）
    public void toggleEndpointStatus(Long id) {
        // 查找对应的 Endpoint
        Endpoint endpoint = endpointRepository.findById(id)
                .orElseThrow(() -> new EndpointNotFoundException("接口未找到"));

        // 切换状态
        endpoint.setStatus(!endpoint.isStatus());
        endpointRepository.save(endpoint);
    }

    // 切换接口的匿名访问设置
    public Endpoint toggleAllowAnonymous(Long id) {
        // 查找对应的 Endpoint
        Endpoint endpoint = endpointRepository.findById(id)
                .orElseThrow(() -> new EndpointNotFoundException("接口未找到"));

        // 切换匿名访问设置
        endpoint.setAllowAnonymous(!endpoint.isAllowAnonymous());
        return endpointRepository.save(endpoint);
    }

    public Page<EndpointDTO> searchEndpoints(String search, Pageable pageable) {
        if (search == null || search.trim().isEmpty()) {
            // 如果搜索条件为空，获取所有数据并转换为 EndpointDTO
            return endpointRepository.findAll(pageable).map(EndpointDTO::convertToDTO);
        }

        // 根据 identifier 或 path 字段进行模糊搜索，查询符合条件的 Endpoint
        return endpointRepository.findByIdentifierContainingOrPathContaining(search, pageable)
                .map(EndpointDTO::convertToDTO);
    }


    public Page<SimpleEndpointDTO> searchSimpleEndpoints(String search, Pageable pageable) {
        if (search == null || search.trim().isEmpty()) {
            return endpointRepository.findAll(pageable).map(this::toSimpleEndpointDTO);
        }
        return endpointRepository.findByIdentifierContainingOrPathContaining(search, pageable)
                .map(this::toSimpleEndpointDTO);
    }

    private SimpleEndpointDTO toSimpleEndpointDTO(Endpoint endpoint) {
        SimpleEndpointDTO dto = new SimpleEndpointDTO();
        dto.setId(endpoint.getId());
        dto.setDisplayName(endpoint.getDisplayName());
        dto.setPath(endpoint.getPath());
        dto.setMethod(endpoint.getMethod());
        dto.setDescription(endpoint.getDescription());
        return dto;
    }

    // 更新接口
    public EndpointDTO updateEndpoint(Long id, EndpointDTO endpointDTO) throws Exception {
        // 根据 id 查找现有的 Endpoint 实体
        Optional<Endpoint> existingEndpointOpt = endpointRepository.findById(id);

        // 如果实体不存在，抛出异常
        if (!existingEndpointOpt.isPresent()) {
            throw new Exception("接口不存在");
        }

        String identifier = endpointDTO.getMethod() + ":" + endpointDTO.getPath();
        // 检查接口路径是否已存在
        if (endpointRepository.existsByIdentifier(identifier)) {
            throw new Exception("接口路径已存在");
        }

        Endpoint existingEndpoint = existingEndpointOpt.get();

        // 更新实体的属性
        existingEndpoint.setDisplayName(endpointDTO.getDisplayName());
        existingEndpoint.setMethod(endpointDTO.getMethod());
        existingEndpoint.setPath(endpointDTO.getPath());
        existingEndpoint.setAccessLevel(endpointDTO.getAccessLevel());
        existingEndpoint.setStatus(endpointDTO.isStatus());
        existingEndpoint.setAllowAnonymous(endpointDTO.isAllowAnonymous());
        existingEndpoint.setIdentifier(identifier);

        // 保存更新后的实体
        Endpoint updatedEndpoint = endpointRepository.save(existingEndpoint);

        // 将更新后的实体转换为 DTO 返回
        return new EndpointDTO(updatedEndpoint);
    }

    // 添加接口
    public EndpointDTO addEndpoint(EndpointDTO endpointDTO) throws Exception {
        // 将 DTO 转换为实体对象
        Endpoint endpoint = endpointDTO.convertToEntity();

        String identifier = endpoint.getMethod() + ":" + endpoint.getPath();

        // 检查接口路径是否已存在
        if (endpointRepository.existsByIdentifier(identifier)) {
            throw new Exception("接口路径已存在");
        }

        endpoint.setIdentifier(identifier);

        // 保存到数据库
        Endpoint savedEndpoint = endpointRepository.save(endpoint);

        // 将保存后的实体对象转换为 DTO
        return new EndpointDTO(savedEndpoint);
    }


    // 删除接口
    public void deleteEndpoint(Long id) throws Exception {
        Endpoint endpoint = endpointRepository.findById(id)
                .orElseThrow(() -> new Exception("接口未找到"));
        endpointRepository.delete(endpoint);
    }

    // 批量删除接口
    public void batchDeleteEndpoints(List<Long> ids) throws Exception {
        List<Endpoint> endpoints = endpointRepository.findAllById(ids);
        if (endpoints.isEmpty()) {
            throw new Exception("没有找到相关接口");
        }
        endpointRepository.deleteAll(endpoints);
    }

    // 为接口分配权限
    public void assignPermissionsToEndpoint(Long endpointId, List<Long> permissionIds) throws Exception {
        // 查找接口实体
        Endpoint endpoint = endpointRepository.findById(endpointId)
                .orElseThrow(() -> new Exception("接口未找到"));

        // 查找所有权限实体
        List<Permission> permissions = permissionRepository.findAllById(permissionIds);
        if (permissions.size() != permissionIds.size()) {
            throw new Exception("部分权限未找到");
        }

        // 绑定权限到接口
        for (Permission permission : permissions) {
            if (!endpoint.getPermissions().contains(permission)) {
                endpoint.addPermission(permission);
            }
        }

        // 更新接口的权限信息
        endpointRepository.save(endpoint);
    }


    // 移除接口权限
    public void removePermissionsFromEndpoint(Long endpointId, List<Long> permissionIds) throws Exception {
        // 查找接口实体
        Endpoint endpoint = endpointRepository.findById(endpointId)
                .orElseThrow(() -> new Exception("接口未找到"));

        // 查找所有权限实体
        List<Permission> permissions = permissionRepository.findAllById(permissionIds);
        if (permissions.size() != permissionIds.size()) {
            throw new Exception("部分权限未找到");
        }

        // 移除权限
        for (Permission permission : permissions) {
            if (endpoint.getPermissions().contains(permission)) {
                endpoint.removePermission(permission);
            }
        }

        // 更新接口的权限信息
        endpointRepository.save(endpoint);
    }

}
